
jQuery.extend({createUploadIframe:function (id, uri) {
			//create frame
	var frameId = "jUploadFrame" + id;
	var iframeHtml = "<iframe id=\"" + frameId + "\" name=\"" + frameId + "\" style=\"position:absolute; top:-9999px; left:-9999px\"";
	if (window.ActiveXObject) {
		if (typeof uri == "boolean") {
			iframeHtml += " src=\"" + "javascript:false" + "\"";
		} else {
			if (typeof uri == "string") {
				iframeHtml += " src=\"" + uri + "\"";
			}
		}
	}
	iframeHtml += " />";
	jQuery(iframeHtml).appendTo(document.body);
	return jQuery("#" + frameId).get(0);
}, createUploadForm:function (id, fileElementId, data) {
		//create form	
	var formId = "jUploadForm" + id;
	var fileId = "jUploadFile" + id;
	var form = jQuery("<form  action=\"\" method=\"POST\" name=\"" + formId + "\" id=\"" + formId + "\" enctype=\"multipart/form-data\"></form>");
	if (data) {
		for (var i in data) {
			jQuery("<input type=\"hidden\" name=\"" + i + "\" value=\"" + data[i] + "\" />").appendTo(form);
		}
	}
	var oldElement = jQuery("#" + fileElementId);
	var newElement = jQuery(oldElement).clone();
	jQuery(oldElement).attr("id", fileId);
	jQuery(oldElement).before(newElement);
	jQuery(oldElement).appendTo(form);
		
		//set attributes
	jQuery(form).css("position", "absolute");
	jQuery(form).css("top", "-1200px");
	jQuery(form).css("left", "-1200px");
	jQuery(form).appendTo("body");
	return form;
}, ajaxFileUpload:function (s) {
        // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout		
	s = jQuery.extend({}, jQuery.ajaxSettings, s);
	var id = new Date().getTime();
	var form = jQuery.createUploadForm(id, s.fileElementId, (typeof (s.data) == "undefined" ? false : s.data));
	var io = jQuery.createUploadIframe(id, s.secureuri);
	var frameId = "jUploadFrame" + id;
	var formId = "jUploadForm" + id;		
        // Watch for a new set of requests
	if (s.global && !jQuery.active++) {
		jQuery.event.trigger("ajaxStart");
	}
	var requestDone = false;
        // Create the request object
	var xml = {};
	if (s.global) {
		jQuery.event.trigger("ajaxSend", [xml, s]);
	}
        // Wait for a response to come back
	var uploadCallback = function (isTimeout) {
		var io = document.getElementById(frameId);
		try {
			if (io.contentWindow) {
				xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
				xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;
			} else {
				if (io.contentDocument) {
					xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML : null;
					xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument : io.contentDocument.document;
				}
			}
		}
		catch (e) {
			jQuery.handleError(s, xml, null, e);
		}
		if (xml || isTimeout == "timeout") {
			requestDone = true;
			var status;
			try {
				status = isTimeout != "timeout" ? "success" : "error";
                    // Make sure that the request was successful or notmodified
				if (status != "error") {
                        // process the data (runs the xml through httpData regardless of callback)
					var data = jQuery.uploadHttpData(xml, s.dataType);    
                        // If a local callback was specified, fire it and pass it the data
					if (s.success) {
						s.success(data, status);
					}
    
                        // Fire the global callback
					if (s.global) {
						jQuery.event.trigger("ajaxSuccess", [xml, s]);
					}
				} else {
					jQuery.handleError(s, xml, status);
				}
			}
			catch (e) {
				status = "error";
				jQuery.handleError(s, xml, status, e);
			}

                // The request was completed
			if (s.global) {
				jQuery.event.trigger("ajaxComplete", [xml, s]);
			}

                // Handle the global AJAX counter
			if (s.global && !--jQuery.active) {
				jQuery.event.trigger("ajaxStop");
			}

                // Process result
			if (s.complete) {
				s.complete(xml, status);
			}
			jQuery(io).unbind();
			setTimeout(function () {
				try {
					jQuery(io).remove();
					jQuery(form).remove();
				}
				catch (e) {
					jQuery.handleError(s, xml, null, e);
				}
			}, 100);
			xml = null;
		}
	};
        // Timeout checker
	if (s.timeout > 0) {
		setTimeout(function () {
                // Check to see if the request is still happening
			if (!requestDone) {
				uploadCallback("timeout");
			}
		}, s.timeout);
	}
	try {
		var form = jQuery("#" + formId);
		jQuery(form).attr("action", s.url);
		jQuery(form).attr("method", "POST");
		jQuery(form).attr("target", frameId);
		if (form.encoding) {
			jQuery(form).attr("encoding", "multipart/form-data");
		} else {
			jQuery(form).attr("enctype", "multipart/form-data");
		}
		jQuery(form).submit();
	}
	catch (e) {
		jQuery.handleError(s, xml, null, e);
	}
	jQuery("#" + frameId).load(uploadCallback);
	return {abort:function () {
	}};
}, uploadHttpData:function (r, type) {
	var data = !type;
	data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
	if (type == "script") {
		jQuery.globalEval(data);
	}
        // Get the JavaScript object, if JSON is used.
	if (type == "json") {
		eval("data = " + data);
	}
        // evaluate scripts within html
	if (type == "html") {
		jQuery("<div>").html(data).evalScripts();
	}
	return data;
},
handleError: function( s, xhr, status, e ){
	// If a local callback was specified, fire it		
	if ( s.error ) {
		s.error.call( s.context || s, xhr, status, e );
	}
	// Fire the global callback
	if ( s.global ) {
		(s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
	}
}
});

